This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.
Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.
plot(cars)

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.
When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).
The UMass Hoops Message board represents the collective inner psyche of the UMass sports fan. It is where the most dedicated, loyal, tormented fans of the UMass Basketball program go to express frustrations, comiserate, stoke each other’s unrealistic expectations, lather themselves into a frenzy, and very occasionally celebrate. I thought it might be interesting to better understand how and when people have used the platform since it began, through a few ups and many downs.
Shall we take a look?
require(networkD3)
Loading required package: networkD3
package 㤼㸱networkD3㤼㸲 was built under R version 3.6.3
Taking a look at when this all began we can see that it started as a trickle in 2003 and gained steam through our our NCAA tournament appearance in the 2013-2014 season. No surprise, but activity is largely condensed to the months of the year when the season is active, from November through March. After the exciting season where Derek Kellogg’s Minutemen got off to a hot start and did just enough to tailspin their way to an NCAA tournament first round spanking at the hands of Tennessee, monthly volume fell back to 2010 levels, peaking at < 3k posts per month in the 2014-15 season.
p.volume <- plot_ly(posts.df, x = ~format(as.Date(PostDateTime), "%Y-%m")) %>%
add_histogram() %>%
layout(title = "UMass Hoops Message Board Posts per Month", yaxis = list(title="", tickformat=",d", gridcolor = "#bbb"), xaxis = list(title="Year-Month"))
p.volume
Ignoring 574 observationsIgnoring 574 observations
Monthly post volumes are a decent way to gauge interest in the program from year to year, but looking at the number of unique individuals that are participating also helps us understand the spread of interest each year. While we still see that the 2013-14 season has the largest number of users, it’s not wildly higher than some of the first years of the message board. During that high water mark, we see there there are >250 unique users that are making posts in a given month. But we see unique monhtly posters north of 200 in a number of other seasons: 2004-05, 2007-08, 2011-12, and 2012-13. In other words, in the “up” years of the program we are seeing more engaged users, but it seems as though much of the difference in total post volume we saw previously is driven by an increase in posts per user rather than just a jump in net new users.
## How many unique posters do we see over time?
unique.posters <- posts.df %>%
mutate(YrMon = format(as.Date(PostDateTime), "%Y-%m")) %>%
group_by(YrMon) %>%
summarize(UniquePosters = n_distinct(poster))
head(unique.posters)
p.uniqueposters <- plot_ly(unique.posters, x = ~YrMon, y = ~UniquePosters, type = "bar") %>%
layout(title = "Unique Posters Per Month", yaxis = list(title="", tickformat=",d", gridcolor = "#bbb"), xaxis = list(title="Year-Month"))
p.uniqueposters
Ignoring 1 observationsIgnoring 1 observations
p.AvgPostsPerUser <- plot_ly(posts.per.poster, x = ~YrMon, y = ~round(AvgPPU, 2), type = "bar") %>%
layout(title = "Average # of Posts Made by Active Posters Each Month", yaxis = list(title="", gridcolor = "#bbb"), xaxis = list(title="Year-Month"))
p.AvgPostsPerUser
Ignoring 1 observationsIgnoring 1 observations
One thing I wondered going through this was about when new people were finding the board, registering, and making their first posts versus if there were people who had signed up early on but were just returning to the board after a hiatus. It was surprising to see that the 2013-14 seasons really didn’t bring a whole lot of net new users to the board, instead it seems to just be previously active users coming back to the board. Also - my knowledge of the early days of the board is limited… but I do know that at some point the backend platform was migrated from one place to another, and it seems like history may have been truncated prior to April 2004 - doesn’t seem likely that there was a one-month surge of new posters right at the start… There were some other times that seem to have drawn in new users. UMass basketball / message board historians may have a better sense for what was happening, but it appears March 2005 when Travis Ford was named head coach likely caused some activity. Then, after new users started to level off, there is another flurry of new users that come in over the span of March-April in 2008, right as UMass made their run with Travis Ford to the NIT finals and he announced he was leaving for Oklahoma State.
p.FirstPost <- plot_ly(first.post, x = ~YrMon, y = ~PostVolume, type = "bar") %>%
layout(title = "First Time Posters", yaxis = list(title="", tickformat=",d", gridcolor = "#bbb"), xaxis = list(title="Year-Month"))
p.FirstPost
Ignoring 1 observationsIgnoring 1 observations
For me and I assume many others, the message board is largely a spectator sport. My guess is that the true extent of the message board community isn’t very well represented in the figures above because of this same behavior by others. The board’s content really is dominated by a select few users. I found 1,175 unique post handles in the time span of data that I scraped, but below you can see the top percentile of these posters make up almost 30 percent of all content posted on the board - that’s just 11 people! The top 3 percent of posters make up more than half of all content (53%), that’s just 35 posters.
p.PosterPrcntle <- plot_ly(prolific, x = ~Percentile, y = ~CumSum.PostPrcn, type = "scatter", mode="markers+lines") %>%
layout(title = "Portion of All Message Board Posts", yaxis = list(title="", tickformat="%", gridcolor = "#bbb"), xaxis = list(title="Poster Percentile by Post Frequency"))
p.PosterPrcntle
One of the commonly used tools on the board that can help us understand a bit more about back and forth dialogue on the board is the quoting functionality. Posters have the ability to quote another post in their own post - essentially highlighting it as a reference for what they are saying. I thought it might give a decent sense for which users are often communicating directly with one another. Below are the quote-quoter frequencies where there are more than 50 occurrences. Looks like there are a few specific users that like to use this functionality more than most - NilesGold, for example.
While the order matters here in terms of who is quoting who - I wanted to take a look at the relationships between posters, abstracting the direction of the quoter-quotee relatinoship. So or example, I want to know only that NilesGold and 69MG have quoted eachother a total of288 times, rather than NilesGold quoting 69MG 162x and vice versa 126x. This will help simplify the relationships between users of the board.
LS0tDQp0aXRsZTogIlVNYXNzIEJhc2tldGJhbGwgTWVzc2FnZSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuIA0KDQpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIA0KDQpgYGB7cn0NCnBsb3QoY2FycykNCmBgYA0KDQpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ3RybCtBbHQrSSouDQoNCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ3RybCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLg0KDQoNClRoZSBVTWFzcyBIb29wcyBNZXNzYWdlIGJvYXJkIHJlcHJlc2VudHMgdGhlIGNvbGxlY3RpdmUgaW5uZXIgcHN5Y2hlIG9mIHRoZSBVTWFzcyBzcG9ydHMgZmFuLiBJdCBpcyB3aGVyZSB0aGUgbW9zdCBkZWRpY2F0ZWQsIGxveWFsLCB0b3JtZW50ZWQgZmFucyBvZiB0aGUgVU1hc3MgQmFza2V0YmFsbCBwcm9ncmFtIGdvIHRvIGV4cHJlc3MgZnJ1c3RyYXRpb25zLCBjb21pc2VyYXRlLCBzdG9rZSBlYWNoIG90aGVyJ3MgdW5yZWFsaXN0aWMgZXhwZWN0YXRpb25zLCBsYXRoZXIgdGhlbXNlbHZlcyBpbnRvIGEgZnJlbnp5LCBhbmQgdmVyeSBvY2Nhc2lvbmFsbHkgY2VsZWJyYXRlLiBJIHRob3VnaHQgaXQgbWlnaHQgYmUgaW50ZXJlc3RpbmcgdG8gYmV0dGVyIHVuZGVyc3RhbmQgaG93IGFuZCB3aGVuIHBlb3BsZSBoYXZlIHVzZWQgdGhlIHBsYXRmb3JtIHNpbmNlIGl0IGJlZ2FuLCB0aHJvdWdoIGEgZmV3IHVwcyBhbmQgbWFueSBkb3ducy4NCg0KU2hhbGwgd2UgdGFrZSBhIGxvb2s/DQoNCmBgYHtyfQ0KIyMgbG9hZCBpbiB0aGUgcGFja2FnZXMgbmVlZGVkDQpyZXF1aXJlKHRpZHlyKQ0KcmVxdWlyZShkcGx5cikNCnJlcXVpcmUoZ2dwbG90MikNCnJlcXVpcmUobHVicmlkYXRlKQ0KcmVxdWlyZShwbG90bHkpDQpyZXF1aXJlKGlncmFwaCkNCnJlcXVpcmUobmV0d29ya0QzKQ0KDQojI1NldCB0aGUgZGF0YSBkaXJlY3RvcnkNCmRhdGEuZGlyIDwtIHBhc3RlMChnZXR3ZCgpLCAiL0hvb3AgQm9hcmQgRGF0YS8iKQ0KDQojIyBsb2FkIGluIHRoZSBtZXNzYWdlIGJvYXJkIHBvc3RzIG5vdyB0aGF0IHRoZXkgaGF2ZSBiZWVuIHNjcmFwZWQgIA0KcG9zdHMuZGYgPC0gcmVhZC5jc3YocGFzdGUwKGRhdGEuZGlyLCAiSG9vcHMgQm9hcmQgUG9zdHMuY3N2IiksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCg0KIyMgY29udmVydCB0aGUgRGF0ZVRpbWUgdmFyaWFibGUgdG8gYW4gYWN0dWFsIGRhdGUgdGltZQ0KcG9zdHMuZGYkUG9zdERhdGVUaW1lIDwtIGFzLlBPU0lYY3QocG9zdHMuZGYkRGF0ZVRpbWUpDQpoZWFkKHBvc3RzLmRmWywgYygiRGF0ZVRpbWUiLCAiUG9zdERhdGVUaW1lIildKQ0KDQojIyBnZXQgcmlnaHQgb2YgdGhlIGNoYXJhY3RlciB2ZXJzaW9uDQpwb3N0cy5kZiREYXRlVGltZSA8LSBOVUxMDQpgYGANCg0KVGFraW5nIGEgbG9vayBhdCB3aGVuIHRoaXMgYWxsIGJlZ2FuIHdlIGNhbiBzZWUgdGhhdCBpdCBzdGFydGVkIGFzIGEgdHJpY2tsZSBpbiAyMDAzIGFuZCBnYWluZWQgc3RlYW0gdGhyb3VnaCBvdXIgb3VyIE5DQUEgdG91cm5hbWVudCBhcHBlYXJhbmNlIGluIHRoZSAyMDEzLTIwMTQgc2Vhc29uLiBObyBzdXJwcmlzZSwgYnV0IGFjdGl2aXR5IGlzIGxhcmdlbHkgY29uZGVuc2VkIHRvIHRoZSBtb250aHMgb2YgdGhlIHllYXIgd2hlbiB0aGUgc2Vhc29uIGlzIGFjdGl2ZSwgZnJvbSBOb3ZlbWJlciB0aHJvdWdoIE1hcmNoLiBBZnRlciB0aGUgZXhjaXRpbmcgc2Vhc29uIHdoZXJlIERlcmVrIEtlbGxvZ2cncyBNaW51dGVtZW4gZ290IG9mZiB0byBhIGhvdCBzdGFydCBhbmQgZGlkIGp1c3QgZW5vdWdoIHRvIHRhaWxzcGluIHRoZWlyIHdheSB0byBhbiBOQ0FBIHRvdXJuYW1lbnQgZmlyc3Qgcm91bmQgc3BhbmtpbmcgYXQgdGhlIGhhbmRzIG9mIFRlbm5lc3NlZSwgbW9udGhseSB2b2x1bWUgZmVsbCBiYWNrIHRvIDIwMTAgbGV2ZWxzLCBwZWFraW5nIGF0IDwgM2sgcG9zdHMgcGVyIG1vbnRoIGluIHRoZSAyMDE0LTE1IHNlYXNvbi4NCg0KYGBge3J9DQoNCiMjIFBsb3QgdGhlIG51bWJlciBvZiBwb3N0cyBwZXIgbW9udGgNCnAudm9sdW1lIDwtIHBsb3RfbHkocG9zdHMuZGYsIHggPSB+Zm9ybWF0KGFzLkRhdGUoUG9zdERhdGVUaW1lKSwgIiVZLSVtIikpICU+JQ0KICBhZGRfaGlzdG9ncmFtKCkgJT4lDQogIGxheW91dCh0aXRsZSA9ICJVTWFzcyBIb29wcyBNZXNzYWdlIEJvYXJkIFBvc3RzIHBlciBNb250aCIsIHlheGlzID0gbGlzdCh0aXRsZT0iIiwgdGlja2Zvcm1hdD0iLGQiLCBncmlkY29sb3IgPSAiI2JiYiIpLCB4YXhpcyA9IGxpc3QodGl0bGU9IlllYXItTW9udGgiKSkNCnAudm9sdW1lDQoNCmBgYA0KDQpNb250aGx5IHBvc3Qgdm9sdW1lcyBhcmUgYSBkZWNlbnQgd2F5IHRvIGdhdWdlIGludGVyZXN0IGluIHRoZSBwcm9ncmFtIGZyb20geWVhciB0byB5ZWFyLCBidXQgbG9va2luZyBhdCB0aGUgbnVtYmVyIG9mIHVuaXF1ZSBpbmRpdmlkdWFscyB0aGF0IGFyZSBwYXJ0aWNpcGF0aW5nIGFsc28gaGVscHMgdXMgdW5kZXJzdGFuZCB0aGUgc3ByZWFkIG9mIGludGVyZXN0IGVhY2ggeWVhci4gV2hpbGUgd2Ugc3RpbGwgc2VlIHRoYXQgdGhlIDIwMTMtMTQgc2Vhc29uIGhhcyB0aGUgbGFyZ2VzdCBudW1iZXIgb2YgdXNlcnMsIGl0J3Mgbm90IHdpbGRseSBoaWdoZXIgdGhhbiBzb21lIG9mIHRoZSBmaXJzdCB5ZWFycyBvZiB0aGUgbWVzc2FnZSBib2FyZC4gRHVyaW5nIHRoYXQgaGlnaCB3YXRlciBtYXJrLCB3ZSBzZWUgdGhlcmUgdGhlcmUgYXJlID4yNTAgdW5pcXVlIHVzZXJzIHRoYXQgYXJlIG1ha2luZyBwb3N0cyBpbiBhIGdpdmVuIG1vbnRoLiBCdXQgd2Ugc2VlIHVuaXF1ZSBtb25odGx5IHBvc3RlcnMgbm9ydGggb2YgMjAwIGluIGEgbnVtYmVyIG9mIG90aGVyIHNlYXNvbnM6IDIwMDQtMDUsIDIwMDctMDgsIDIwMTEtMTIsIGFuZCAyMDEyLTEzLiBJbiBvdGhlciB3b3JkcywgaW4gdGhlICJ1cCIgeWVhcnMgb2YgdGhlIHByb2dyYW0gd2UgYXJlIHNlZWluZyBtb3JlIGVuZ2FnZWQgdXNlcnMsIGJ1dCBpdCBzZWVtcyBhcyB0aG91Z2ggbXVjaCBvZiB0aGUgZGlmZmVyZW5jZSBpbiB0b3RhbCBwb3N0IHZvbHVtZSB3ZSBzYXcgcHJldmlvdXNseSBpcyBkcml2ZW4gYnkgYW4gaW5jcmVhc2UgaW4gcG9zdHMgcGVyIHVzZXIgcmF0aGVyIHRoYW4ganVzdCBhIGp1bXAgaW4gbmV0IG5ldyB1c2Vycy4gICANCg0KYGBge3J9DQoNCiMjIEhvdyBtYW55IHVuaXF1ZSBwb3N0ZXJzIGRvIHdlIHNlZSBvdmVyIHRpbWU/DQp1bmlxdWUucG9zdGVycyA8LSAgcG9zdHMuZGYgJT4lDQogIG11dGF0ZShZck1vbiA9IGZvcm1hdChhcy5EYXRlKFBvc3REYXRlVGltZSksICIlWS0lbSIpKSAlPiUNCiAgZ3JvdXBfYnkoWXJNb24pICU+JQ0KICBzdW1tYXJpemUoVW5pcXVlUG9zdGVycyA9IG5fZGlzdGluY3QocG9zdGVyKSkNCg0KaGVhZCh1bmlxdWUucG9zdGVycykNCg0KcC51bmlxdWVwb3N0ZXJzIDwtIHBsb3RfbHkodW5pcXVlLnBvc3RlcnMsIHggPSB+WXJNb24sIHkgPSB+VW5pcXVlUG9zdGVycywgdHlwZSA9ICJiYXIiKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gIlVuaXF1ZSBQb3N0ZXJzIFBlciBNb250aCIsIHlheGlzID0gbGlzdCh0aXRsZT0iIiwgdGlja2Zvcm1hdD0iLGQiLCBncmlkY29sb3IgPSAiI2JiYiIpLCB4YXhpcyA9IGxpc3QodGl0bGU9IlllYXItTW9udGgiKSkNCnAudW5pcXVlcG9zdGVycw0KDQpgYGANCmBgYHtyfQ0KDQojIyBIb3cgbWFueSBwb3N0cyBwZXIgYWN0aXZlIHVzZXIgZG8gd2Ugc2VlIG92ZXIgdGltZT8NCnBvc3RzLnBlci5wb3N0ZXIgPC0gIHBvc3RzLmRmICU+JQ0KICBtdXRhdGUoWXJNb24gPSBmb3JtYXQoYXMuRGF0ZShQb3N0RGF0ZVRpbWUpLCAiJVktJW0iKSkgJT4lDQogIGdyb3VwX2J5KFlyTW9uLCBwb3N0ZXIpICU+JQ0KICBzdW1tYXJpemUoUG9zdFZvbHVtZSA9IG4oKSkgJT4lDQogIGdyb3VwX2J5KFlyTW9uKSAlPiUNCiAgc3VtbWFyaXplKEF2Z1BQVSA9IG1lYW4oUG9zdFZvbHVtZSkpDQoNCmhlYWQocG9zdHMucGVyLnBvc3RlcikNCg0KcC5BdmdQb3N0c1BlclVzZXIgPC0gcGxvdF9seShwb3N0cy5wZXIucG9zdGVyLCB4ID0gfllyTW9uLCB5ID0gfnJvdW5kKEF2Z1BQVSwgMSksIHR5cGUgPSAiYmFyIikgJT4lDQogIGxheW91dCh0aXRsZSA9ICJBdmVyYWdlICMgb2YgUG9zdHMgTWFkZSBieSBBY3RpdmUgUG9zdGVycyBFYWNoIE1vbnRoIiwgeWF4aXMgPSBsaXN0KHRpdGxlPSIiLCBncmlkY29sb3IgPSAiI2JiYiIpLCB4YXhpcyA9IGxpc3QodGl0bGU9IlllYXItTW9udGgiKSkNCnAuQXZnUG9zdHNQZXJVc2VyDQoNCmBgYA0KDQoNCk9uZSB0aGluZyBJIHdvbmRlcmVkIGdvaW5nIHRocm91Z2ggdGhpcyB3YXMgYWJvdXQgd2hlbiBuZXcgcGVvcGxlIHdlcmUgZmluZGluZyB0aGUgYm9hcmQsIHJlZ2lzdGVyaW5nLCBhbmQgbWFraW5nIHRoZWlyIGZpcnN0IHBvc3RzIHZlcnN1cyBpZiB0aGVyZSB3ZXJlIHBlb3BsZSB3aG8gaGFkIHNpZ25lZCB1cCBlYXJseSBvbiBidXQgd2VyZSBqdXN0IHJldHVybmluZyB0byB0aGUgYm9hcmQgYWZ0ZXIgYSBoaWF0dXMuIEl0IHdhcyBzdXJwcmlzaW5nIHRvIHNlZSB0aGF0IHRoZSAyMDEzLTE0IHNlYXNvbnMgcmVhbGx5IGRpZG4ndCBicmluZyBhIHdob2xlIGxvdCBvZiBuZXQgbmV3IHVzZXJzIHRvIHRoZSBib2FyZCwgaW5zdGVhZCBpdCBzZWVtcyB0byBqdXN0IGJlIHByZXZpb3VzbHkgYWN0aXZlIHVzZXJzIGNvbWluZyBiYWNrIHRvIHRoZSBib2FyZC4gQWxzbyAtIG15IGtub3dsZWRnZSBvZiB0aGUgZWFybHkgZGF5cyBvZiB0aGUgYm9hcmQgaXMgbGltaXRlZC4uLiBidXQgSSBkbyBrbm93IHRoYXQgYXQgc29tZSBwb2ludCB0aGUgYmFja2VuZCBwbGF0Zm9ybSB3YXMgbWlncmF0ZWQgZnJvbSBvbmUgcGxhY2UgdG8gYW5vdGhlciwgYW5kIGl0IHNlZW1zIGxpa2UgaGlzdG9yeSBtYXkgaGF2ZSBiZWVuIHRydW5jYXRlZCBwcmlvciB0byBBcHJpbCAyMDA0IC0gZG9lc24ndCBzZWVtIGxpa2VseSB0aGF0IHRoZXJlIHdhcyBhIG9uZS1tb250aCBzdXJnZSBvZiBuZXcgcG9zdGVycyByaWdodCBhdCB0aGUgc3RhcnQuLi4gVGhlcmUgd2VyZSBzb21lIG90aGVyIHRpbWVzIHRoYXQgc2VlbSB0byBoYXZlIGRyYXduIGluIG5ldyB1c2Vycy4gVU1hc3MgYmFza2V0YmFsbCAvIG1lc3NhZ2UgYm9hcmQgaGlzdG9yaWFucyBtYXkgaGF2ZSBhIGJldHRlciBzZW5zZSBmb3Igd2hhdCB3YXMgaGFwcGVuaW5nLCBidXQgaXQgYXBwZWFycyBNYXJjaCAyMDA1IHdoZW4gVHJhdmlzIEZvcmQgd2FzIG5hbWVkIGhlYWQgY29hY2ggbGlrZWx5IGNhdXNlZCBzb21lIGFjdGl2aXR5LiBUaGVuLCBhZnRlciBuZXcgdXNlcnMgc3RhcnRlZCB0byBsZXZlbCBvZmYsIHRoZXJlIGlzIGFub3RoZXIgZmx1cnJ5IG9mIG5ldyB1c2VycyB0aGF0IGNvbWUgaW4gb3ZlciB0aGUgc3BhbiBvZiBNYXJjaC1BcHJpbCBpbiAyMDA4LCByaWdodCBhcyBVTWFzcyBtYWRlIHRoZWlyIHJ1biB3aXRoIFRyYXZpcyBGb3JkIHRvIHRoZSBOSVQgZmluYWxzIGFuZCBoZSBhbm5vdW5jZWQgaGUgd2FzIGxlYXZpbmcgZm9yIE9rbGFob21hIFN0YXRlLg0KDQpgYGB7cn0NCmZpcnN0LnBvc3QgPC0gcG9zdHMuZGYgJT4lDQogIGFycmFuZ2UocG9zdGVyLCBQb3N0RGF0ZVRpbWUpICU+JQ0KICBncm91cF9ieShwb3N0ZXIpICU+JQ0KICBzbGljZSgxKSAlPiUNCiAgbXV0YXRlKFlyTW9uID0gZm9ybWF0KGFzLkRhdGUoUG9zdERhdGVUaW1lKSwgIiVZLSVtIikpICU+JQ0KICBncm91cF9ieShZck1vbikgJT4lDQogIHN1bW1hcml6ZShQb3N0Vm9sdW1lID0gbigpKQ0KICANCnAuRmlyc3RQb3N0IDwtIHBsb3RfbHkoZmlyc3QucG9zdCwgeCA9IH5Zck1vbiwgeSA9IH5Qb3N0Vm9sdW1lLCB0eXBlID0gImJhciIpICU+JQ0KICBsYXlvdXQodGl0bGUgPSAiRmlyc3QgVGltZSBQb3N0ZXJzIiwgeWF4aXMgPSBsaXN0KHRpdGxlPSIiLCB0aWNrZm9ybWF0PSIsZCIsIGdyaWRjb2xvciA9ICIjYmJiIiksIHhheGlzID0gbGlzdCh0aXRsZT0iWWVhci1Nb250aCIpKQ0KcC5GaXJzdFBvc3QNCg0KYGBgDQoNCkZvciBtZSBhbmQgSSBhc3N1bWUgbWFueSBvdGhlcnMsIHRoZSBtZXNzYWdlIGJvYXJkIGlzIGxhcmdlbHkgYSBzcGVjdGF0b3Igc3BvcnQuIE15IGd1ZXNzIGlzIHRoYXQgdGhlIHRydWUgZXh0ZW50IG9mIHRoZSBtZXNzYWdlIGJvYXJkIGNvbW11bml0eSBpc24ndCB2ZXJ5IHdlbGwgcmVwcmVzZW50ZWQgaW4gdGhlIGZpZ3VyZXMgYWJvdmUgYmVjYXVzZSBvZiB0aGlzIHNhbWUgYmVoYXZpb3IgYnkgb3RoZXJzLiBUaGUgYm9hcmQncyBjb250ZW50IHJlYWxseSBpcyBkb21pbmF0ZWQgYnkgYSBzZWxlY3QgZmV3IHVzZXJzLiBJIGZvdW5kIDEsMTc1IHVuaXF1ZSBwb3N0IGhhbmRsZXMgaW4gdGhlIHRpbWUgc3BhbiBvZiBkYXRhIHRoYXQgSSBzY3JhcGVkLCBidXQgYmVsb3cgeW91IGNhbiBzZWUgdGhlIHRvcCBwZXJjZW50aWxlIG9mIHRoZXNlIHBvc3RlcnMgbWFrZSB1cCBhbG1vc3QgMzAgcGVyY2VudCBvZiBhbGwgY29udGVudCBwb3N0ZWQgb24gdGhlIGJvYXJkIC0gdGhhdCdzIGp1c3QgMTEgcGVvcGxlISBUaGUgdG9wIDMgcGVyY2VudCBvZiBwb3N0ZXJzIG1ha2UgdXAgbW9yZSB0aGFuIGhhbGYgb2YgYWxsIGNvbnRlbnQgKDUzJSksIHRoYXQncyBqdXN0IDM1IHBvc3RlcnMuDQoNCmBgYHtyfQ0KcG9zdHMudHRsIDwtIG5yb3cocG9zdHMuZGYpDQpwb3N0ZXJzLnR0bCA8LSBsZW5ndGgodW5pcXVlKHBvc3RzLmRmJHBvc3RlcikpDQpwcm9saWZpYyA8LSBwb3N0cy5kZiAlPiUNCiAgZ3JvdXBfYnkocG9zdGVyKSAlPiUNCiAgc3VtbWFyaXplKHBvc3QuZnJlcSA9IG4oKSkgJT4lDQogIG11dGF0ZShQcmNudCA9IHBvc3QuZnJlcS9wb3N0cy50dGwpICU+JQ0KICBhcnJhbmdlKGRlc2MoUHJjbnQpKSAlPiUNCiAgbXV0YXRlKFBlcmNlbnRpbGUgPSBmbG9vcigxMDAqKHJvd19udW1iZXIoKS9wb3N0ZXJzLnR0bCkpKSAlPiUNCiAgZ3JvdXBfYnkoUGVyY2VudGlsZSkgJT4lDQogIHN1bW1hcml6ZShQb3N0LlByY250ID0gc3VtKFByY250KSkgJT4lDQogIG11dGF0ZShDdW1TdW0uUG9zdFByY24gPSBjdW1zdW0oUG9zdC5QcmNudCkpDQoNCg0KcC5Qb3N0ZXJQcmNudGxlIDwtIHBsb3RfbHkocHJvbGlmaWMsIHggPSB+UGVyY2VudGlsZSwgeSA9IH5DdW1TdW0uUG9zdFByY24sIHR5cGUgPSAic2NhdHRlciIsIG1vZGU9Im1hcmtlcnMrbGluZXMiKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gIlBvcnRpb24gb2YgQWxsIE1lc3NhZ2UgQm9hcmQgUG9zdHMiLCB5YXhpcyA9IGxpc3QodGl0bGU9IiIsIHRpY2tmb3JtYXQ9IiUiLCBncmlkY29sb3IgPSAiI2JiYiIpLCB4YXhpcyA9IGxpc3QodGl0bGU9IlBvc3RlciBQZXJjZW50aWxlIGJ5IFBvc3QgRnJlcXVlbmN5IikpDQpwLlBvc3RlclByY250bGUNCg0KICANCmBgYA0KDQoNCk9uZSBvZiB0aGUgY29tbW9ubHkgdXNlZCB0b29scyBvbiB0aGUgYm9hcmQgdGhhdCBjYW4gaGVscCB1cyB1bmRlcnN0YW5kIGEgYml0IG1vcmUgYWJvdXQgYmFjayBhbmQgZm9ydGggZGlhbG9ndWUgb24gdGhlIGJvYXJkIGlzIHRoZSBxdW90aW5nIGZ1bmN0aW9uYWxpdHkuIFBvc3RlcnMgaGF2ZSB0aGUgYWJpbGl0eSB0byBxdW90ZSBhbm90aGVyIHBvc3QgaW4gdGhlaXIgb3duIHBvc3QgLSBlc3NlbnRpYWxseSBoaWdobGlnaHRpbmcgaXQgYXMgYSByZWZlcmVuY2UgZm9yIHdoYXQgdGhleSBhcmUgc2F5aW5nLiBJIHRob3VnaHQgaXQgbWlnaHQgZ2l2ZSBhIGRlY2VudCBzZW5zZSBmb3Igd2hpY2ggdXNlcnMgYXJlIG9mdGVuIGNvbW11bmljYXRpbmcgZGlyZWN0bHkgd2l0aCBvbmUgYW5vdGhlci4gQmVsb3cgYXJlIHRoZSBxdW90ZS1xdW90ZXIgZnJlcXVlbmNpZXMgd2hlcmUgdGhlcmUgYXJlIG1vcmUgdGhhbiA1MCBvY2N1cnJlbmNlcy4gTG9va3MgbGlrZSB0aGVyZSBhcmUgYSBmZXcgc3BlY2lmaWMgdXNlcnMgdGhhdCBsaWtlIHRvIHVzZSB0aGlzIGZ1bmN0aW9uYWxpdHkgbW9yZSB0aGFuIG1vc3QgLSBOaWxlc0dvbGQsIGZvciBleGFtcGxlLg0KDQpgYGB7cn0NCiMjIGV4dHJhY3QgdGhlIHRleHQgYmVmb3JlIHRoZSBzdWJzdHJpbmcgJ3dyb3RlOicgd2hpY2ggYWx3YXlzIHByb2NlZWRzIHRoZSBxdW90ZXMgaW4gdGhlIG1lc3NhZ2UgYm9keQ0KcG9zdHMuZGYkUXVvdGUgPC0gaWZlbHNlKGdyZXBsKCJ3cm90ZToiLCBwb3N0cy5kZiRwb3N0cywgZml4ZWQgPSBUUlVFKSwgc3ViKCIgd3JvdGU6LioiLCAiIiwgcG9zdHMuZGYkcG9zdHMpLCAiIikNCg0KIyMgY2hlY2sgdG8gc2VlIGlmIHRoZXJlIGFyZSBhbnkgd2VpcmQgdmFsdWVzIC0gaWYgc28gc3RyaXAgdGhlbSBvdXQNCnVuaXF1ZS5wb3N0ZXJzIDwtIHVuaXF1ZShwb3N0cy5kZiRwb3N0ZXIpDQpwb3N0cy5kZiRRdW90ZSA8LSBpZmVsc2UocG9zdHMuZGYkUXVvdGUgJWluJSB1bmlxdWUucG9zdGVycywgcG9zdHMuZGYkUXVvdGUsICIiKQ0KDQojIyBzdW1tYXJpemUgdGhlIHBhaXJpbmdzIG9mIGNvbnZlcnNhdGlvbnMNCnF1b3RlLnN1bW1hcnkgPC0gcG9zdHMuZGYgJT4lDQogIGZpbHRlcihRdW90ZSAhPSAiIikgJT4lDQogIGdyb3VwX2J5KHBvc3RlciwgUXVvdGUpICU+JQ0KICBzdW1tYXJpemUoZnJlcSA9IG4oKSkgJT4lDQogIGFycmFuZ2UoZGVzYyhmcmVxKSkNCg0KIyMgV2hvJ3MgcXVvdGluZyB3aG8/DQpxdW90ZS5zdW1tYXJ5JExhYmVsIDwtIHBhc3RlMChxdW90ZS5zdW1tYXJ5JHBvc3RlciwgIiAtICIsIHF1b3RlLnN1bW1hcnkkUXVvdGUpDQoNCiMjIG5lZWQgdG8gY3JlYXRlIGZhY3RvciBmb3IgcGxvdHRpbmcNCnF1b3RlLnN1bW1hcnkkTGFiZWwgPC0gZmFjdG9yKHF1b3RlLnN1bW1hcnkkTGFiZWwpDQpxdW90ZS5zdW1tYXJ5JExhYmVsIDwtIHJlb3JkZXIocXVvdGUuc3VtbWFyeSRMYWJlbCwgcXVvdGUuc3VtbWFyeSRmcmVxKQ0KDQogIA0KDQpwLkZyZXFRdW90ZXJzIDwtIHBsb3RfbHkocXVvdGUuc3VtbWFyeVtxdW90ZS5zdW1tYXJ5JGZyZXE+PTUwICYgb3JkZXIocXVvdGUuc3VtbWFyeSRmcmVxKSwgXSwgeCA9IH5mcmVxLCB5ID0gfkxhYmVsLCB0eXBlID0gImJhciIsIG9yaWVudGF0aW9uPSJoIikgJT4lDQogIGxheW91dCh0aXRsZSA9ICJRdW90ZSBGcmVxdWVuY3kiLCB5YXhpcyA9IGxpc3QodGl0bGU9IlF1b3RlciAtIFF1b3RlZSIsIGdyaWRjb2xvciA9ICIjYmJiIiksIHhheGlzID0gbGlzdCh0aXRsZT0iRnJlcXVlbmN5IikpDQpwLkZyZXFRdW90ZXJzDQoNCmBgYA0KDQpXaGlsZSB0aGUgb3JkZXIgbWF0dGVycyBoZXJlIGluIHRlcm1zIG9mIHdobyBpcyBxdW90aW5nIHdobyAtIEkgd2FudGVkIHRvIHRha2UgYSBsb29rIGF0IHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gcG9zdGVycywgYWJzdHJhY3RpbmcgdGhlIGRpcmVjdGlvbiBvZiB0aGUgcXVvdGVyLXF1b3RlZSByZWxhdGlub3NoaXAuIFNvIG9yIGV4YW1wbGUsIEkgd2FudCB0byBrbm93IG9ubHkgdGhhdCBOaWxlc0dvbGQgYW5kIDY5TUcgaGF2ZSBxdW90ZWQgZWFjaG90aGVyIGEgdG90YWwgb2YyODggdGltZXMsIHJhdGhlciB0aGFuIE5pbGVzR29sZCBxdW90aW5nIDY5TUcgMTYyeCBhbmQgdmljZSB2ZXJzYSAxMjZ4LiBUaGlzIHdpbGwgaGVscCBzaW1wbGlmeSB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHVzZXJzIG9mIHRoZSBib2FyZC4gDQoNCmBgYHtyfQ0KDQpmb3IgKGkgaW4gYygyOm5yb3cocXVvdGUuc3VtbWFyeSkpKXsNCiAgdGVtcCA8LSBxdW90ZS5zdW1tYXJ5W2MoMTppLTEpLCBdDQogIGlmKG5yb3codGVtcFt0ZW1wJFF1b3RlID09IHF1b3RlLnN1bW1hcnlbaSwgXSRwb3N0ZXIgJiB0ZW1wJHBvc3RlciA9PSBxdW90ZS5zdW1tYXJ5W2ksIF0kUXVvdGUsIF0pID09MSl7DQogICAgcCA8LSBxdW90ZS5zdW1tYXJ5W2ksIF0kcG9zdGVyDQogICAgcSA8LSBxdW90ZS5zdW1tYXJ5W2ksIF0kUXVvdGUNCiAgICBxdW90ZS5zdW1tYXJ5W2ksIF0kcG9zdGVyIDwtIHENCiAgICBxdW90ZS5zdW1tYXJ5W2ksIF0kUXVvdGUgPC0gcA0KICAgIHAgPC0gTlVMTA0KICAgIHE8LSBOVUxMDQogICAgfQ0KICB0ZW1wIDwtIE5VTEwNCn0NCg0KIyMgbm93IHJlc3VtbWFyaXplDQpxdW90ZS5zdW1tYXJ5MiA8LSBxdW90ZS5zdW1tYXJ5ICU+JQ0KICBncm91cF9ieShwb3N0ZXIsIFF1b3RlKSAlPiUNCiAgc3VtbWFyaXplKFN1bSA9IHN1bShmcmVxKSkgJT4lDQogIGZpbHRlcihTdW0gPj0gNDApICU+JQ0KICBhcnJhbmdlKGRlc2MoU3VtKSkNCg0KIyMgY3JlYXRlIG5vZGUgLyBsaW5rcyBkYXRhZnJhbWVzDQp1c2VybmFtZXMgPC0gdW5pcXVlKGMocXVvdGUuc3VtbWFyeTIkcG9zdGVyLCBxdW90ZS5zdW1tYXJ5MiRRdW90ZSkpDQppZCA8LSBjKDE6bGVuZ3RoKHVzZXJuYW1lcykpDQpNaXNOb2RlczEgPC0gZGF0YS5mcmFtZSh1c2VybmFtZXMgPSB1c2VybmFtZXMsIGlkID0gaWQsIGdyb3VwID0gMSwgc2l6ZSA9IDEpDQoNCnF1b3RlLnN1bW1hcnkyIDwtIG1lcmdlKHggPSBxdW90ZS5zdW1tYXJ5MiwgeSA9IE1pc05vZGVzMVssIGMoInVzZXJuYW1lcyIsICJpZCIpXSwgYnkueCA9ICJwb3N0ZXIiLCBieS55ID0gInVzZXJuYW1lcyIpDQpuYW1lcyhxdW90ZS5zdW1tYXJ5MikgPC0gYygicG9zdGVyIiwgIlF1b3RlIiwgIlN1bSIsICJzb3VyY2UiKQ0KcXVvdGUuc3VtbWFyeTIgPC0gbWVyZ2UoeCA9IHF1b3RlLnN1bW1hcnkyLCB5ID0gTWlzTm9kZXMxWywgYygidXNlcm5hbWVzIiwgImlkIildLCBieS54ID0gIlF1b3RlIiwgYnkueSA9ICJ1c2VybmFtZXMiKQ0KbmFtZXMocXVvdGUuc3VtbWFyeTIpIDwtIGMoInBvc3RlciIsICJRdW90ZSIsICJTdW0iLCAic291cmNlIiwgInRhcmdldCIpDQoNCnF1b3RlLnN1bW1hcnkyIDwtIHF1b3RlLnN1bW1hcnkyICU+JQ0KICBhcnJhbmdlKHNvdXJjZSkNCg0KZm9yY2VOZXR3b3JrKExpbmtzID0gcXVvdGUuc3VtbWFyeTIsIE5vZGVzID0gTWlzTm9kZXMxLCBTb3VyY2UgPSAicG9zdGVyIiwgVGFyZ2V0ID0gIlF1b3RlIiwgDQogICAgICAgICAgICAgem9vbSA9IFRSVUUsIFZhbHVlID0gIlN1bSIsIE5vZGVJRCA9ICJ1c2VybmFtZXMiLCBHcm91cCA9ICJncm91cCIpDQpgYGANCg0K